﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace ManPowerEngine
{
	public class Transform
	{
		/// <summary>
		/// Position relative to its parent
		/// </summary>
		public Vector LocalPosition = Vector.Zero;

		/// <summary>
		/// Rotation relative to its parent
		/// </summary>
		public double LocalRotation = 0;

		/// <summary>
		/// The game object which this transform belongs to.
		/// </summary>
		private GameObject mGameObject;

		internal Transform(GameObject go)
		{
			mGameObject = go;
		}

		/// <summary>
		/// Absolute position of this GameObject
		/// </summary>
		public Vector Position
		{
			get {
				if (mGameObject.IsRoot)
				{
					return LocalPosition;
				}
				else
				{
					return mGameObject.Parent.Transform.LocalToAbsolutePosition(LocalPosition);
				}
			}
			set {
				if (mGameObject.IsRoot)
				{
					LocalPosition = value;
				}
				else
				{
					LocalPosition = mGameObject.Parent.Transform.AbsoluteToLocalPosition(value);
				}
			}
		}

		/// <summary>
		/// perform a movement according to current rotation
		/// </summary>
		/// <param name="localvector">a local movement vector</param>
		public void Translate(Vector localvector)
		{
			LocalPosition += localvector.Rotate(LocalRotation);
		}

		/// <summary>
		/// Absolute rotation of this GameObject
		/// </summary>
		public double Rotation
		{
			get
			{
				if (mGameObject.IsRoot)
				{
					return LocalRotation;
				}
				else
				{
					return mGameObject.Parent.Transform.Rotation + LocalRotation;
				}
			}
			set {
				if (mGameObject.IsRoot)
				{
					LocalRotation = value;
				}
				else
				{
					LocalRotation = value - mGameObject.Parent.Transform.Rotation;
				}
			}
		}

		/// <summary>
		/// make the rotation pointing the point specified
		/// </summary>
		/// <param name="abslocation">the absolute position of the point</param>
		public void LookAt(Vector abslocation)
		{
			Vector rel = abslocation - Position;
			if (rel.IsZero)
			{
				return;
			}
			Log.Debug(rel);
			Rotation = Vector.AngleBetween(rel, Vector.XAxis);
		}

		/// <summary>
		/// Transfer a local vector into the absolute position
		/// </summary>
		/// <param name="localposition">local position relative this game object</param>
		/// <returns>absolute position of that point</returns>
		public Vector LocalToAbsolutePosition(Vector localposition)
		{
			if (mGameObject.IsRoot)
			{
				return localposition;
			}
			else
			{
				return Position + localposition.Rotate(Rotation);
			}
		}

		/// <summary>
		/// Transfer a local vector direction into absolute space
		/// </summary>
		/// <param name="localposition">local vector relative this game object</param>
		/// <returns>absolute vector of that point</returns>
		public Vector LocalToAbsoluteVector(Vector localvector)
		{
			if (mGameObject.IsRoot)
			{
				return localvector;
			}
			else
			{
				return localvector.Rotate(Rotation);
			}
		}

		/// <summary>
		/// Transfer a absolute vector into a local position
		/// </summary>
		/// <param name="absoluteposition">the absolute position</param>
		/// <returns>the local position of this point</returns>
		public Vector AbsoluteToLocalPosition(Vector absoluteposition)
		{
			if (mGameObject.IsRoot)
			{
				return absoluteposition;
			}
			else
			{
				return (absoluteposition - Position).Rotate(-Rotation);
			}
		}

		/// <summary>
		/// Transfer a absolute vector into a local direction
		/// </summary>
		/// <param name="absoluteposition">the absolute vector</param>
		/// <returns>the local vector direction</returns>
		public Vector AbsoluteToLocalVector(Vector absolutevector)
		{
			if (mGameObject.IsRoot)
			{
				return absolutevector;
			}
			else
			{
				return absolutevector.Rotate(-Rotation);
			}
		}
	}
}
